home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / winlib.lzh / WINLIB / MENU.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-04  |  14.2 KB  |  208 lines

  1. /*
  2.  *    Menu module
  3.  *
  4.  *    Copyright (c) Clever Bits and Bitgate Software 1993
  5.  *    All Rights Reserved.
  6.  *
  7.  *    Handles menus and stuff
  8.  *
  9.  *    [12.9.93 Karl A. 0ygard
  10.  *        not documented
  11.  *    [31.10.93] Karl A. 0ygard
  12.  *                            - changed some code layout
  13.  *    [2.11.93] Karl A. 0ygard
  14.  *        domenu                - changed some code layout
  15.  *    [7.11.93 - 3.4.94] Karl A. 0ygard and Ken Hollis
  16.  *        domenu                - fixed bug to do with menus that go
  17.  *                                outside screen on left side
  18.  *        DoDeskMenu            - added for desktop menu management, and
  19.  *                                side-drop down menus
  20.  *                            - finally got the routines working for
  21.  *                                side-drop down menus after two days
  22.  *        WMenuAttach            - added for obvious reasons
  23.  *
  24.  *    Karl: Added siderooted menu bars!  Something we've both been
  25.  *    waiting for for a long time.  Also added a desktop menu routine,
  26.  *    but it doesn't work with MultiTOS, or Geneva...  We will probably
  27.  *    need to windowize this...  It's easy enough to do anyway.  We
  28.  *    also need to add these routines to the windowed routines...
  29.  */
  30.  
  31. #include <vdi.h>
  32. #include <stddef.h>
  33. #include <stdio.h>
  34. #include "winlib.h"
  35.  
  36. #ifdef __TURBOC__
  37. #pragma warn -pia
  38. #endif
  39.  
  40. #ifndef __MENU__
  41. #define __MENU__
  42. #endif
  43.  
  44. MFDB screen;                            /* Screen mfdb */
  45.  
  46. /*
  47.  *    Update menu box in window
  48.  *
  49.  *    win = Window to update
  50.  *    x, y, w, h = Area to redraw
  51.  */
  52. GLOBAL void WUpdateWindowMenu(WINDOW *win, int x, int y, int w, int h)
  53. {
  54.     if (win->menubar) {
  55.         GRECT own, temp;
  56.  
  57.         own.g_x = x;
  58.         own.g_y = y;
  59.         own.g_w = w;
  60.         own.g_h = h;
  61.  
  62.         objc_offset(win->menubar, 1, &temp.g_x, &temp.g_y);
  63.         temp.g_w = win->menubar[1].ob_width;
  64.         temp.g_h = win->menubar[1].ob_height + 1;
  65.  
  66.         if (rc_intersect(&own, &temp)) {
  67.             wind_update(BEG_UPDATE);
  68.     
  69.             WWindGet(win, WF_FIRSTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
  70.             while (temp.g_w && temp.g_h) {
  71.                 if (rc_intersect(&temp, &own))
  72.                     objc_draw(win->menubar, 1, 2, temp.g_x, temp.g_y, temp.g_w, temp.g_h);
  73.                 WWindGet(win, WF_NEXTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
  74.             }
  75.     
  76.             wind_update(END_UPDATE);
  77.         }
  78.     }
  79. }
  80.  
  81. /*
  82.  *    Show or delete menubar
  83.  *
  84.  *    me_btree = tree structure of menubar to show
  85.  *    me_bshow = if 0, deletes menubar
  86.  *               if 1, shows menubar
  87.  *
  88.  *    (This call *should* be used when putting a menubar on the screen.
  89.  *     This is so that the program can always know what menubar is being
  90.  *     used and to provide full restoring of menus when an item has been
  91.  *     selected.)
  92.  */
  93. GLOBAL int WMenuBar(OBJECT *me_btree, int me_bshow)
  94. {
  95.     wl_menubar = me_bshow ? me_btree : 0;
  96.  
  97.     if (!me_bshow) {
  98.         MenusShown = FALSE;
  99.         return objc_draw(desktop, 0, 99, me_btree->ob_x, me_btree->ob_y, me_btree->ob_width, me_btree[1].ob_height);
  100.     } else {
  101.         MenusShown = TRUE;
  102.         return objc_draw(me_btree, 0, 99, me_btree->ob_x, me_btree->ob_y, me_btree->ob_width, me_btree[1].ob_height);
  103.     }
  104. }
  105.  
  106.  
  107. /*
  108.  *    Menu handling and stuff
  109.  *
  110.  *    win = window in which menu is to be manipulated
  111.  *
  112.  *    (This is one hell of a mess.)
  113.  */
  114. GLOBAL void domenu(WINDOW *win)
  115. {
  116.     GRECT work, mrct;
  117.     OBJECT *dm_menubar;
  118.     int mx, my, button, dummy;
  119.     int message, pulldown = -1, oldpull = -1, menu, entry;
  120.     int selection = -1;
  121.     int x, y, w, h, tx, ty;
  122.     void *ourbuffer;
  123.  
  124.     graf_mkstate(&mx, &my, &button, &dummy);
  125.  
  126.     wind_get(win->handle, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);
  127.  
  128.     wind_update(BEG_MCTRL);
  129.     dm_menubar = win->menubar;
  130.  
  131.     do {
  132.         graf_mkstate(&mx, &my, &button, &dummy);
  133.  
  134.         if (pulldown == -1) {
  135.             if ((dummy = objc_find(dm_menubar, 1, 2, mx, my)) > 1)
  136.                 if (!(dm_menubar[dummy].ob_state & DISABLED))
  137.                     pulldown = dummy;
  138.         } else {
  139.             if (oldpull != pulldown) {        /* Changed pulldown? */
  140.                 menu = dm_menubar[dm_menubar[dm_menubar->ob_head].ob_next].ob_head;
  141.                 for (dummy = pulldown - 3; dummy > 0; dummy--)
  142.                     menu = dm_menubar[menu].ob_next;
  143.  
  144.                 objc_offset(dm_menubar, menu, &x, &y);
  145.                 objc_offset(dm_menubar, pulldown, &tx, &ty);
  146.                 x--;
  147.                 y--;
  148.                 w = dm_menubar[menu].ob_width + 1;
  149.                 h = dm_menubar[menu].ob_height + 1;
  150.  
  151.                 oldpull = pulldown;
  152.  
  153.                 objc_change(dm_menubar, pulldown, 0, 0, 0, 0, 0, dm_menubar[menu].ob_state | SELECTED, 0);
  154.                 objc_offset(dm_menubar, oldpull, &mrct.g_x, &mrct.g_y);
  155.                 mrct.g_w = dm_menubar[oldpull].ob_width;
  156.                 mrct.g_h = dm_menubar[oldpull].ob_height;
  157.                 if (rc_intersect(&mrct, &work))
  158.                     WUpdateWindowMenu(win, mrct.g_x, mrct.g_y, mrct.g_w, mrct.g_h);
  159.  
  160.                 if ((tx = (x + w) - (desk.g_x + desk.g_w)) < 0)
  161.                     if (x < 8)
  162.                         tx = x - 8;
  163.                     else
  164.                         tx = 0;
  165.                 else
  166.                         tx += 8;
  167.  
  168.                 if (((y + h) - (desk.g_y + desk.g_h)) < 0)
  169.                     ty = 0;
  170.                 else
  171.                     ty -= y + h;
  172.  
  173.                 x -= tx;
  174.                 y += ty;
  175.                 dm_menubar[menu].ob_x -= tx;
  176.                 dm_menubar[menu].ob_y += ty;
  177.  
  178.                 ourbuffer = scrsave(VDIhandle, x, y, x + w, y + h);
  179.                 objc_draw(dm_menubar, menu, 2, 0, 0, 16383, 16383);
  180.             }
  181.  
  182.             if ((dummy = objc_find(dm_menubar, 1, 2, mx, my)) > 1)    /* Within a menu? */ {
  183.                 if (work.g_x + work.g_w > mx && !(dm_menubar[dummy].ob_state & DISABLED))
  184.                     pulldown = dummy;                                    /* Menu within window and enabled? */
  185.             } else                                    /* Within pulldown */
  186.                 if ((entry = objc_find(dm_menubar, menu, 1, mx, my)) > menu) {
  187.                     EVENT event;
  188.  
  189.                     event.ev_mflags = MU_BUTTON | MU_M1 | MU_M2;
  190.                     event.ev_mbclicks = 1;
  191.                     event.ev_bmask = 0x13;
  192.                     event.ev_mbstate = 0;
  193.  
  194.                     objc_offset(dm_menubar, menu, &event.ev_mm2x, &event.ev_mm2y);
  195.                     event.ev_mm2width = dm_menubar[menu].ob_width;
  196.                     event.ev_mm2height = dm_menubar[menu].ob_height;
  197.                     event.ev_mm1flags = event.ev_mm2flags = 1;
  198.  
  199.                     do {
  200.                         if (!(dm_menubar[entry].ob_state & DISABLED))
  201.                             objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state | SELECTED, 1);
  202.  
  203.                         objc_offset(dm_menubar, entry, &event.ev_mm1x, &event.ev_mm1y);
  204.                         event.ev_mm1width = dm_menubar[entry].ob_width;
  205.                         event.ev_mm1height = dm_menubar[entry].ob_height;
  206.  
  207.                         message = EvntMulti(&event);
  208.  
  209.                         if (!(dm_menubar[entry].ob_state & DISABLED))
  210.                             if (message == MU_BUTTON) {
  211.                                 selection = entry;
  212.                                 dm_menubar[entry].ob_state &= ~SELECTED;
  213.                             } else
  214.                                 objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
  215.  
  216.                         if (message & MU_M1)
  217.                             entry = objc_find(dm_menubar, menu, 1, event.ev_mmox, event.ev_mmoy);
  218.                     } while (!(message & MU_M2) && !(message == MU_BUTTON));
  219.                 }
  220.  
  221.             if (oldpull != pulldown || !button || selection != -1) {
  222.                 scrrestore(ourbuffer);
  223.  
  224.                 objc_change(dm_menubar, oldpull, 0, 0, 0, 0, 0, dm_menubar[menu].ob_state & ~SELECTED, 0);
  225.                 objc_offset(dm_menubar, oldpull, &mrct.g_x, &mrct.g_y);
  226.                 mrct.g_w = dm_menubar[oldpull].ob_width;
  227.                 mrct.g_h = dm_menubar[oldpull].ob_height;
  228.                 if (rc_intersect(&mrct, &work))
  229.                     WUpdateWindowMenu(win, mrct.g_x, mrct.g_y, mrct.g_w, mrct.g_h);
  230.             }
  231.         }
  232.     } while (button && selection == -1);
  233.  
  234.     no_click();
  235.     wind_update(END_MCTRL);
  236.  
  237.     if (selection != -1) {
  238.         int msg_buf[8] = {MN_SELECTED, 0, 0, 0, 0, 0, 0, 0};
  239.  
  240.         msg_buf[3] = pulldown;
  241.         msg_buf[4] = selection;
  242.  
  243.         WCallWndDispatcher(win, msg_buf);
  244.     }
  245. }
  246.  
  247. /*
  248.  *    Menu handling and stuff
  249.  *
  250.  *    win = window in which menu is to be manipulated
  251.  *
  252.  *    (This is one hell of a mess.)
  253.  */
  254. GLOBAL void DoDeskMenu(OBJECT *men)
  255. {
  256.     GRECT mrct;
  257.     OBJECT *dm_menubar;
  258.     int mx, my, button, dummy;
  259.     void *ourbuffer;
  260.     int message, pulldown = -1, oldpull = -1, menu = -1, entry = -1;
  261.     int selection = -1;
  262.     int sideroot = 0, sideobj = 0;
  263.     int x, y, w, h, tx, ty;
  264.  
  265.     dm_menubar = men;
  266.  
  267.     do {
  268.         graf_mkstate(&mx, &my, &button, &dummy);
  269.  
  270.         if (pulldown == -1) {
  271.             if ((dummy = objc_find(dm_menubar, 1, 2, mx, my)) > 1)
  272.                 if (!(dm_menubar[dummy].ob_state & DISABLED))
  273.                     pulldown = dummy;
  274.         } else {
  275.             if (oldpull != pulldown) {        /* Changed pulldown? */
  276.                 menu = dm_menubar[dm_menubar[dm_menubar->ob_head].ob_next].ob_head;
  277.                 for (dummy = pulldown - 3; dummy > 0; dummy--)
  278.                     menu = dm_menubar[menu].ob_next;
  279.  
  280.                 objc_offset(dm_menubar, menu, &x, &y);
  281.                 objc_offset(dm_menubar, pulldown, &tx, &ty);
  282.                 x--;
  283.                 y--;
  284.                 w = dm_menubar[menu].ob_width + 1;
  285.                 h = dm_menubar[menu].ob_height + 1;
  286.  
  287.                 oldpull = pulldown;
  288.  
  289.                 objc_change(dm_menubar, pulldown, 0, 0, 0, 0, 0, dm_menubar[menu].ob_state | SELECTED, 1);
  290.                 objc_offset(dm_menubar, oldpull, &mrct.g_x, &mrct.g_y);
  291.                 mrct.g_w = dm_menubar[oldpull].ob_width;
  292.                 mrct.g_h = dm_menubar[oldpull].ob_height;
  293.  
  294.                 if ((tx = (x + w) - (desk.g_x + desk.g_w)) < 0)
  295.                     if (x < 8)
  296.                         tx = x - 8;
  297.                     else
  298.                         tx = 0;
  299.                 else
  300.                         tx += 8;
  301.  
  302.                 if (((y + h) - (desk.g_y + desk.g_h)) < 0)
  303.                     ty = 0;
  304.                 else
  305.                     ty -= y + h;
  306.  
  307.                 x -= tx;
  308.                 y += ty;
  309.                 dm_menubar[menu].ob_x -= tx;
  310.                 dm_menubar[menu].ob_y += ty;
  311.  
  312.                 ourbuffer = scrsave(VDIhandle, x, y, x + w, y + h);
  313.  
  314.                 objc_draw(dm_menubar, menu, 2, 0, 0, 16383, 16383);
  315.             }
  316.  
  317.             if ((dummy = objc_find(dm_menubar, 1, 2, mx, my)) > 1)    /* Within a menu? */ {
  318.                 if (desk.g_x + desk.g_w > mx && !(dm_menubar[dummy].ob_state & DISABLED))
  319.                     pulldown = dummy;                                    /* Menu within window and enabled? */
  320.             } else                                    /* Within pulldown */
  321.                 if ((entry = objc_find(dm_menubar, menu, 1, mx, my)) > menu) {
  322.                     EVENT event;
  323.  
  324.                     event.ev_mflags = MU_BUTTON | MU_M1 | MU_M2;
  325.                     event.ev_mbclicks = 1;
  326.                     event.ev_bmask = 0x101;
  327.                     event.ev_mbstate = 1;
  328.  
  329.                     objc_offset(dm_menubar, menu, &event.ev_mm2x, &event.ev_mm2y);
  330.                     event.ev_mm2width = dm_menubar[menu].ob_width;
  331.                     event.ev_mm2height = dm_menubar[menu].ob_height;
  332.                     event.ev_mm1flags = event.ev_mm2flags = 1;
  333.  
  334.                     do {
  335.                         if (!(dm_menubar[entry].ob_state & DISABLED))
  336.                             if ((entry > 0) && !(dm_menubar[entry].ob_state & DRAW3D))
  337.                                 objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state | SELECTED, 1);
  338.  
  339.                         if (dm_menubar[entry].ob_flags & MENUSIDE) {
  340.                             int tempx, tempy, tempobj;
  341.                             OBJECT *p;
  342.  
  343.                             tempobj = (dm_menubar[entry].ob_type >> 8);
  344.                             if (tempobj) {
  345.                                 rsrc_gaddr(R_TREE, tempobj, &p);
  346.  
  347.                                 objc_offset(dm_menubar, menu, &tempx, &tempy);
  348.  
  349.                                 PMovePopupCoord(p, tempx + dm_menubar[menu].ob_width + dm_menubar[entry].ob_x, tempy + dm_menubar[entry].ob_y);
  350.                                 PShowPopupDesk(p);
  351.                                 sideobj = PDoPopupDeskMenu(p, &button);
  352.                                 sideroot = tempobj;
  353.  
  354.                                 event.ev_mm1width = dm_menubar[entry].ob_width + p->ob_width;
  355.                                 event.ev_mm1height = dm_menubar[entry].ob_height;
  356.                             }
  357.                         }
  358.  
  359.                         objc_offset(dm_menubar, entry, &event.ev_mm1x, &event.ev_mm1y);
  360.  
  361.                         if (!(dm_menubar[entry].ob_flags & MENUSIDE)) {
  362.                             event.ev_mm1width = dm_menubar[entry].ob_width;
  363.                             event.ev_mm1height = dm_menubar[entry].ob_height;
  364.                         }
  365.  
  366.                         message = EvntMulti(&event);
  367.  
  368.                         if (message & MU_M2)
  369.                             if (dm_menubar[entry].ob_flags & MENUSIDE) {
  370.                                 int tempx, tempy, tempobj, xxx;
  371.                                 OBJECT *p;
  372.  
  373.                                 graf_mkstate(&tempx, &tempy, &xxx, &xxx);
  374.                                 tempobj = (dm_menubar[entry].ob_type >> 8);
  375.                                 if (tempobj) {
  376.                                     rsrc_gaddr(R_TREE, tempobj, &p);
  377.                                     if ((dm_menubar[entry].ob_state & SELECTED) && (objc_find(p, 0, 99, tempx, tempy)!=-1)) {
  378.                                         sideobj = PDoPopupDeskMenu(p, &button);
  379.                                         sideroot = tempobj;
  380.                                         message &= ~MU_M2;
  381.                                     } else {
  382.                                         objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
  383.                                         PEndPopupDesk(p);
  384.                                         sideobj = sideroot = 0;
  385.                                         entry = objc_find(dm_menubar, menu, 1, event.ev_mmox, event.ev_mmoy);
  386.                                     }
  387.                                 }
  388.                             }
  389.  
  390.                         if (!(dm_menubar[entry].ob_state & DISABLED))
  391.                             if (message == MU_BUTTON) {
  392.                                 selection = entry;
  393.                                 dm_menubar[entry].ob_state &= ~SELECTED;
  394.                                 if (dm_menubar[entry].ob_flags & MENUSIDE) {
  395.                                     int tempobj;
  396.                                     OBJECT *p;
  397.  
  398.                                     tempobj = (dm_menubar[entry].ob_type >> 8);
  399.                                     if (tempobj) {
  400.                                         rsrc_gaddr(R_TREE, tempobj, &p);
  401.                                         if (entry > 0)
  402.                                             objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
  403.                                         sideobj = sideroot = 0;
  404.                                         PEndPopupDesk(p);
  405.                                     }
  406.                                 } else
  407.                                     objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
  408.                             } else
  409.                                 if (dm_menubar[entry].ob_flags & MENUSIDE) {
  410.                                     int tempobj;
  411.                                     OBJECT *p;
  412.  
  413.                                     tempobj = (dm_menubar[entry].ob_type >> 8);
  414.                                     if (tempobj) {
  415.                                         rsrc_gaddr(R_TREE, tempobj, &p);
  416.                                         if (entry > 0)
  417.                                             objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
  418.                                         PEndPopupDesk(p);
  419.                                     }
  420.                                 } else
  421.                                     if (entry > 0)
  422.                                         objc_change(dm_menubar, entry, 0, 0, 0, 32767, 32767, dm_menubar[entry].ob_state & ~SELECTED, 1);
  423.  
  424.                         if (button)
  425.                             message |= MU_BUTTON;
  426.  
  427.                         if (message & MU_M1)
  428.                             entry = objc_find(dm_menubar, menu, 1, event.ev_mmox, event.ev_mmoy);
  429.                     } while (!(message & MU_M2) && !(message == MU_BUTTON));
  430.  
  431.                     if (message == MU_BUTTON)
  432.                         button = TRUE;
  433.                 }
  434.  
  435.             if (oldpull != pulldown || button || message == MU_BUTTON || selection != -1) {
  436.                 scrrestore(ourbuffer);
  437.  
  438.                 objc_change(dm_menubar, oldpull, 0, 0, 0, 0, 0, dm_menubar[menu].ob_state & ~SELECTED, 1);
  439.                 objc_offset(dm_menubar, oldpull, &mrct.g_x, &mrct.g_y);
  440.                 mrct.g_w = dm_menubar[oldpull].ob_width;
  441.                 mrct.g_h = dm_menubar[oldpull].ob_height;
  442.             }
  443.  
  444.             if (dm_menubar[entry].ob_flags & MENUSIDE) {
  445.                 int tempobj;
  446.                 OBJECT *p;
  447.  
  448.                 tempobj = (dm_menubar[entry].ob_type >> 8);
  449.                 if (tempobj) {
  450.                     rsrc_gaddr(R_TREE, tempobj, &p);
  451.                     PEndPopupDesk(p);
  452.                 }
  453.             }
  454.         }
  455.     } while (!button);
  456.  
  457.     if (pulldown) {
  458.         int msg_buf[8] = {MN_SELECTED, 0, 0, 0, 0, 0, 0, 0};
  459.  
  460.         msg_buf[1] = Ap_ID;
  461.         msg_buf[3] = pulldown;
  462.         msg_buf[4] = entry;
  463.         msg_buf[5] = sideroot;
  464.         msg_buf[6] = sideobj;
  465.  
  466.         appl_write(Ap_ID, 16, msg_buf);
  467.     }
  468. }
  469.  
  470. /*
  471.  *    Attach a popup menu bar to a menu item
  472.  *    by Ken Hollis
  473.  *
  474.  *    Simply stores the index to find whenever an item is selected
  475.  *    inside a menu with our menu routines.  The index is stored in the
  476.  *    upper eight bits as an index within the object type.  (What a
  477.  *    hack!)
  478.  */
  479. GLOBAL void WMenuAttach(OBJECT *menubar, int menuitem, int popupobj, BOOL attach)
  480. {
  481. /*    if (attach)
  482.         menubar[menuitem].ob_type = menubar[menuitem].ob_type | (popupobj << 8);
  483.     else
  484.         menubar[menuitem].ob_type = menubar[menuitem].ob_type | (0 << 8); */
  485. }